package com.atguigu.sync;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

//可重入锁： 进入第一把锁，第一把锁没释放，第一把锁内层的所有锁都能进入
public class SyncLockDemo {

    public synchronized void add() {
        add();
    }

    public static void main(String[] args) {

        lock();
//        sync();

        // 调用时报StackOverflowError，会重复调用，说明synchronized是可重入锁，不然就会使串行的执行状态
       // new SyncLockDemo().add();
       // synchronized



    }


    private static void sync() {

        Object o = new Object();
        new Thread(()->{
            synchronized(o) {
                System.out.println(Thread.currentThread().getName()+" 外层");

                synchronized (o) {
                    System.out.println(Thread.currentThread().getName()+" 中层");

                    synchronized (o) {
                        System.out.println(Thread.currentThread().getName()+" 内层");
                    }
                }
            }

        },"t1").start();

    }


    private static void lock() {

        //Lock演示可重入锁
        Lock lock = new ReentrantLock();
        //创建线程
        new Thread(()->{
            try {
                //上锁
                lock.lock();
                System.out.println(Thread.currentThread().getName()+" 外层");

                try {
                    //上锁
                    lock.lock();
                    System.out.println(Thread.currentThread().getName()+" 内层");
                }finally {
                    //释放锁
                    lock.unlock();
                }
            }finally {
                //释放锁
                lock.unlock();
            }
        },"t1").start();

        /**
         * 创建新线程
         * （上一个线程中，如果其中一个锁没释放，执行该新线程，
         *   lock.lock()获取不到锁，aaaa没有打印出来，程序也一直阻塞）
         */
        new Thread(()->{
            // 当上面代码没有释放锁时，此处会获取不到锁，无法执行打印aaaa代码
            lock.lock();
            System.out.println("aaaa");
            lock.unlock();
        },"aa").start();
    }

}
